package com.logic.config.netty;

import com.logic.config.netty.web.handler.WebSocketChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class NettyServer {
    public void start(Integer port) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            // 添加自定义的业务处理器
                            ch.pipeline().addLast(new MyServerHandler());
                        }
                    });
            ChannelFuture future = bootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public void startWebSocketServer(Integer port) {
        // 使用多Reactor多线程模型，EventLoopGroup相当于线程池，内部维护一个或多个线程（EventLoop），每个EventLoop可处理多个Channel（单线程处理多个IO任务）
        // 创建主线程组EventLoopGroup，专门负责建立连接
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 创建子线程组，专门负责IO任务的处理
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workGroup);
            b.channel(NioServerSocketChannel.class);
            b.childHandler(new WebSocketChannelInitializer());
            log.info("Netty WebSocket Server is starting...");
            Channel ch = b.bind(port).sync().channel();
            log.info("Netty WebSocket Server started on port {}", port);

            //创建一个定长线程池，支持定时及周期性任务执行
            // ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);
            // WebSocketInfoService webSocketInfoService = new WebSocketInfoService();
            // //定时任务:扫描所有的Channel，关闭失效的Channel
            // executorService.scheduleAtFixedRate(webSocketInfoService::scanNotActiveChannel,
            //         3, 60, TimeUnit.SECONDS);
            //
            // //定时任务:向所有客户端发送Ping消息
            // executorService.scheduleAtFixedRate(webSocketInfoService::sendPing,
            //         3, 50, TimeUnit.SECONDS);

            ch.closeFuture().sync();
        } catch (Exception e) {
            log.error("Netty WebSocket Server start error", e);
        } finally {
//            //退出程序
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
